using UnityEngine;
using System;
using System.Collections.Generic;
using Object = UnityEngine.Object;
using GameCore;
namespace GameLogic 
{
    public class ResourceManager : Singleton<ResourceManager>
    {
        /// <summary>
        /// 资源路径管理类
        /// </summary>
        private static ResourcePathConfig ResPathConfig;
        /// <summary>
        /// 已加载成功的资源缓存Map。加载完成时加进来
        /// </summary>
        private Dictionary<string, Object> loadedAsset = new Dictionary<string, Object>();
        /// <summary>
        /// 加载失败列表
        /// </summary>
        private List<string> failedMap = new List<string>();
        public void Init()
        {
            //加载ResourcePathConfig
            InitResourcesConfig();

        }

        /// <summary>
        /// 初始化资源路径配置
        /// </summary>
        public void InitResourcesConfig() {
            if (AppConst.IsReleaseVer)
            {
                AssetBundleLoader ab = App.ABMgr.LoadAssetBundle("ManagedResources/Configs/ResourcePathConfig" + AppConst.ABExtName);
                ResPathConfig = ab.LoadAsset<ResourcePathConfig>("ResourcePathConfig");
            }
            else {
                ResPathConfig = LoadAssetEditor<ResourcePathConfig>("Assets/ManagedResources/Configs/ResourcePathConfig.asset");

            }
            ResPathConfig.AnalyticData();

        }

        /// <summary>
        /// 销毁资源
        /// </summary>
        void OnDestroy()
        {
            ClearAsset();
            ResPathConfig = null;
        }

        /// <summary>
        /// 获取缓存的资源
        /// </summary>
        private T GetAsset<T>(string assetName) where T : Object
        {
            Object obj = null;
            if (loadedAsset.TryGetValue(assetName, out obj)) {
                return obj as T;
            }
            return null;
        }


        /// <summary>
        /// 同步加载asset资源
        /// </summary>
        public T LoadAsset<T>(string assetName) where T : Object
        {
            T pb = GetAsset<T>(assetName);
            if (pb != null)
                return pb;
            if (AppConst.IsReleaseVer)
            {
                string path = ResPathConfig.GetABName(assetName);
                if (string.IsNullOrEmpty(path))
                {
                    GameCore.Logger.LogErrorFormat("没有找到包含资源{0}的AssetBundle！", assetName);
                    return null;
                }
                AssetBundleLoader loader = App.ABMgr.LoadAssetBundle(path);
                if (IsMono<T>())
                {
					GameObject gameObj  = loader.LoadAsset<GameObject>(assetName);
					if (gameObj != null)
						pb = gameObj.GetComponent<T> ();
                }
                else {
                    pb = loader.LoadAsset<T>(assetName);
                }
            }
            else
            {

				try{
					var perfabPath = "";
					perfabPath = ResPathConfig.GetPath(assetName);
					if (IsMono<T>())
						pb = LoadAssetEditor<GameObject> (perfabPath).GetComponent<T>();
					else 
						pb = LoadAssetEditor<T>(perfabPath);
					
				}
				catch(Exception e){
                    GameCore.Logger.LogError ("同步加载资源失败："+ assetName + "/n" + e.ToString());
				}
            }
            if (pb) AddToMap(assetName, pb);
            return pb;
        }

        /// <summary>
        /// 是否是Mono脚本
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private bool IsMono<T>() {
            return typeof(MonoBehaviour).IsAssignableFrom(typeof(T));
        }

        /// <summary>
        /// 异步加载asset方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="assetName"></param>
        /// <param name="callBack"></param>
        public void LoadAssetAsync<T>(string assetName, Action<string, T> callBack) where T : Object
        {
            GameCore.Logger.Log("LoadAssetAsync:" + assetName);
            T pb = GetAsset<T>(assetName);
            if (pb != null)
            {
                callBack(assetName, pb);
                return;
            }
            if (AppConst.IsReleaseVer)
            {
                string path = ResPathConfig.GetABName(assetName);
                if (string.IsNullOrEmpty(path)) {
                    GameCore.Logger.LogErrorFormat("没有找到包含资源{0}的AssetBundle！", assetName);
                    return;
                }
                App.ABMgr.LoadAssetBundleAsyn(path, (loader) => {
                    pb = GetAsset<T>(assetName);
                    if (pb == null)
                    {
                        if (IsMono<T>())
                        {
							GameObject gameObj  = loader.LoadAsset<GameObject>(assetName);
							if(gameObj != null)
								pb = gameObj.GetComponent<T>();
                        }
                        else
                        {
                            pb = loader.LoadAsset<T>(assetName);
                        }
                        if (pb) AddToMap(assetName, pb);
                    }
                    callBack(assetName, pb);
                });
            }
            else
            {
				try{
					var perfabPath = "";
					perfabPath = ResPathConfig.GetPath(assetName);
					if (IsMono<T>())
						pb = LoadAssetEditor<GameObject> (perfabPath).GetComponent<T>();
					else 
						pb = LoadAssetEditor<T>(perfabPath);
					callBack(assetName, pb);
				}
				catch(Exception e){
                    GameCore.Logger.LogError ("同步加载资源失败："+ assetName);
				}
				finally{
                    if(pb) AddToMap(assetName,pb);
				}
            }
        }

		/// <summary>
		/// 添加到资源缓存中
		/// </summary>
		/// <param name="assetName">Asset name.</param>
		/// <param name="asset">Asset.</param>
        private void AddToMap(string assetName,Object asset) {
			if (!loadedAsset.ContainsKey (assetName)) {
				loadedAsset.Add (assetName, asset);
			} else {
                GameCore.Logger.LogError ("重复加载资源："+ assetName);
			}
        }

        /// <summary>
        /// 删除一个asset缓存,并不会释放内存需要手动调用 Resources.UnloadUnusedAssets();
        /// </summary>
        public void RemoveAsset(string assetName)
        {
            if (!loadedAsset.ContainsKey(assetName)) return;
            loadedAsset.Remove(assetName);
        }


        /// <summary>
        ///  删除一个asset缓存,并卸载资源
        /// </summary>
        public void UnLoadAsset(string assetName) {
            Object asset = null;
            if (loadedAsset.TryGetValue(assetName, out asset)) {
                loadedAsset.Remove(assetName);
                Resources.UnloadAsset(asset);
            }
        }


        /// <summary>
        /// 清空管理器缓存的AssetObject
        /// </summary>
        public void ClearAsset()
        {
            loadedAsset.Clear();
            Resources.UnloadUnusedAssets();
        }

        T LoadAssetEditor<T>(string path) where T: Object {
            T t = null;
#if UNITY_EDITOR
            t = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(path);
#endif
            return t;
        }

    }
}